package com.ls.fw.data.impl.nosql.hbase.server;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeoutException;

import net.rubyeye.xmemcached.MemcachedClient;
import net.rubyeye.xmemcached.MemcachedClientBuilder;
import net.rubyeye.xmemcached.MemcachedClientStateListener;
import net.rubyeye.xmemcached.XMemcachedClientBuilder;
import net.rubyeye.xmemcached.exception.MemcachedException;
import net.rubyeye.xmemcached.utils.AddrUtil;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * 緩存服务
 * @author ls
 * 2015年2月12日下午5:25:14
 */
public class CacheClient {
	
	protected Logger logger = LoggerFactory.getLogger(CacheClient.class);
	
	public static final String PORT = "11211";
	
	public static final int timeout = 5000;//5s
	public static final int OpTimeout = 20;//10ms
	
	private String address = "";
	
	private MemcachedClient memcachedClient = null;
	
	private int threadOpenCount = 0;
	private StateListener listener = new StateListener();
	private MemcachedClientBuilder builder = null;
	
	/**
	 * 是否开启缓存
	 */
	private boolean open = true;
	
	private boolean connected = false;
	
	 
	public CacheClient() {
		super();
	}

	public CacheClient(String address) {
		super();
		this.address = address;
	}

	public CacheClient(String address, boolean open) {
		super();
		this.address = address;
		this.open = open;
	}

	public  void open(){
		open(address);
	}
	
	/**
	 * 打开连接缓存服务
	 * @author ls 2014-7-9 下午05:08:24
	 * @throws IOException
	 */
	public  synchronized void open(String address){
		if(open && !connected && (memcachedClient==null || memcachedClient.isShutdown())){
			long begin = System.currentTimeMillis();
			logger.info("address:"+address);
			builder = new XMemcachedClientBuilder(AddrUtil
					.getAddresses(address));
			builder.setConnectTimeout(timeout);
			builder.setOpTimeout(OpTimeout);
			try {
				if(memcachedClient==null){
					memcachedClient = builder.build();
					memcachedClient.addStateListener(listener);
				}
				String msg = "open-緩存服務耗时:"+(System.currentTimeMillis()-begin);
				logger.info(msg);
				connected = true;
			} catch (IOException e) {
				memcachedClient = null;
				logger.warn(e.getMessage(),e);
			}
		}
	}
	
	 class StateListener implements MemcachedClientStateListener{
		
		@Override
		public void onStarted(MemcachedClient arg0) {
			logger.info("**缓存服务***onStarted****");
		}
		
		@Override
		public void onShutDown(MemcachedClient arg0) {
			logger.warn("**缓存服务***onShutDown****");
			connected = false;
		}
		
		@Override
		public void onException(MemcachedClient arg0, Throwable arg1) {
			logger.debug("**缓存服务***onException****");
			connected = false;
			
		}
		
		@Override
		public void onDisconnected(MemcachedClient arg0, InetSocketAddress arg1) {
			logger.warn("**缓存服务***onDisconnected****");
			connected = false;
			
		}
		
		@Override
		public void onConnected(MemcachedClient arg0, InetSocketAddress arg1) {
			logger.info("**缓存服务***onConnected****");
			connected = true;
			
		}
	}

	public  void flush(){
		if(!isShutdown()){
			try {
				memcachedClient.flushAll();
			} catch (Exception e) {
				logger.warn(e.getMessage(),e);
			}
		}
	}
	
	public  synchronized void close(){
		if(!isShutdown()){
			try {
				//builder.removeStateListener(listener);
				memcachedClient.removeStateListener(listener);
				memcachedClient.shutdown();
				logger.info("關閉服務");
				connected = false;
			} catch (Exception e) {
				logger.warn(e.getMessage(),e);
			}
			memcachedClient = null;
		}
	}
	
	/**
	 * 是否關閉
	 * @author ls 2014-7-9 下午05:26:36
	 * @return
	 */
	public  boolean isShutdown(){
		if(memcachedClient!=null && !memcachedClient.isShutdown()){
			return false;
		}
		return true;
	}
	
	
	/**
	 * 獲取值
	 * @author ls 2014-7-9 下午05:19:20
	 * @param key
	 * @return
	 */
	public  <T> T get(String key){
		if(open && !StringUtils.isBlank(key) &&!isShutdown()){
			try {
				//System.out.println("获取："+key+"-"+memcachedClient.get(key));
				return memcachedClient.get(key);
			} catch (TimeoutException e) {
				logger.warn(e.getMessage(),e);
			} catch (InterruptedException e) {
				logger.warn(e.getMessage(),e);
			} catch (MemcachedException e) {
				logger.warn(e.getMessage(),e);
			}
		}
		return null;
	}
	
	
	/**
	 * 添加值
	 * @author ls 2014-7-9 下午05:19:28
	 * @param name
	 * @param obj
	 * @return
	 */
	public  boolean put(String name,Object obj){
		if(open && !StringUtils.isBlank(name) && !isShutdown()){
			try {
				//System.out.println("添加："+name+"-"+obj);
				memcachedClient.delete(name);
				return memcachedClient.add(name, 0, obj);
			} catch (TimeoutException e) {
				logger.warn(e.getMessage(),e);
			} catch (InterruptedException e) {
				logger.warn(e.getMessage(),e);
			} catch (MemcachedException e) {
				logger.warn(e.getMessage(),e);
			}
		}
		return false;
	}
	
	
	/**
	 * 刪除值
	 * @author ls 2014-7-9 下午05:26:46
	 * @param name
	 * @return
	 */
	public  boolean delete(String name){
		if(open && !StringUtils.isBlank(name) && !isShutdown()){
			try {
				return memcachedClient.delete(name);
			} catch (TimeoutException e) {
				logger.warn(e.getMessage(),e);
			} catch (InterruptedException e) {
				logger.warn(e.getMessage(),e);
			} catch (MemcachedException e) {
				logger.warn(e.getMessage(),e);
			}
		}
		return false;
	}
	
	private  class OpenConnectThread implements Runnable{
		@Override
		public void run() {
			try{
				connect();
			}catch (Exception e) {
				e.printStackTrace();
			}
		}
		private void connect(){
			synchronized (OpenConnectThread.class) {
				if(isShutdown()){
					threadOpenCount++;
					System.out.println("開啟連接線程"+threadOpenCount+"!");
					open(address);
					System.out.println("連接線程"+threadOpenCount+"結束!");
				}
			}
		}
	}
	
	private  void connect(){
		if(open && !connected){
			Thread t = new Thread(new OpenConnectThread());
			t.setDaemon(true);
			t.start();
		}
	}
	
	/**
	 * 顯示服務狀態信息
	 * @author ls 2014-7-9 下午05:45:46
	 */
	public  void printStat() {
		Map<InetSocketAddress, Map<String, String>> stats = null;
		if(!isShutdown()){
			try {
				stats = memcachedClient.getStats();
			} catch (TimeoutException e) {
				logger.warn(e.getMessage(),e);
			} catch (InterruptedException e) {
				logger.warn(e.getMessage(),e);
			} catch (MemcachedException e) {
				logger.warn(e.getMessage(),e);
			}
		}else{
			connect();
		}
		if(stats!=null){
			Set<InetSocketAddress> keys = stats.keySet();
			Iterator<InetSocketAddress> keyIter = keys.iterator();
			while (keyIter.hasNext()) {
				InetSocketAddress key = (InetSocketAddress)keyIter.next();
				Map<String, String> value = stats.get(key);
				System.out.println(key + "=" + value);
				Set<String> keys1 = value.keySet();
				Iterator<String> keyIter1 = keys1.iterator();
				while (keyIter1.hasNext()) {
					String key1 = (String)keyIter1.next();
					Object value1 = value.get(key1);
					System.out.println(key1 + "=" + value1);
				}
				
			}
		}
	}
	
	public boolean isOpen() {
		return open;
	}

	public void setOpen(boolean open) {
		this.open = open;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	/**
	 * @return the connected
	 */
	public boolean isConnected() {
		return connected;
	}

	/**
	 * @param connected the connected to set
	 */
	public void setConnected(boolean connected) {
		this.connected = connected;
	}
	
	
}
